import { io } from 'socket.io-client';
import { ElMessage } from 'element-plus';
import router from '@/router';

class SocketIOService {
    constructor() {
        this.socket = null;
        this.isConnected = false;
        this.reconnectAttempts = 0;
        this.maxReconnectAttempts = 5;
        this.reconnectInterval = 3000;
        this.listeners = new Map();
        this.imKey = null;
    }

    // 初始化连接
    connect(url, imKey) {
        if (!imKey) {
            console.warn('Socket: 未提供imKey，无法建立连接');
            return;
        }

        // 如果已经连接，且 imKey 相同，则不需要重新连接
        if (this.socket && this.isConnected && this.imKey === imKey) {
            return;
        }

        // 如果已经有 socket 实例，先断开旧连接
        if (this.socket) {
            this.disconnect();
        }

        this.imKey = imKey;

        this.socket = io(url, {
            transports: ['websocket'],
            timeout: 5000,
            query: {
                imKey: this.imKey
            },
            reconnection: true,
            reconnectionAttempts: this.maxReconnectAttempts,
            reconnectionDelay: this.reconnectInterval
        });

        this.setupListeners();
    }

    // 设置基础事件监听
    setupListeners() {
        this.socket.on('connect', () => {
            console.log('Socket connected');
            this.isConnected = true;
            this.reconnectAttempts = 0;
            ElMessage.success('实时通讯已连接');
        });

        this.socket.on('disconnect', (reason) => {
            console.log('Socket disconnected:', reason);
            this.isConnected = false;
            if (this.imKey) {
                ElMessage.warning('实时通讯已断开');
            }
        });

        this.socket.on('connect_error', (error) => {
            console.error('Connection error:', error);
            // 如果是认证错误，可能是 imKey 过期
            if (error.message === 'auth failed' || error.message.includes('authentication')) {
                this.handleAuthError();
            }
        });

        // 监听重连事件
        this.socket.on('reconnect_attempt', (attemptNumber) => {
            console.log(`正在尝试重连... (${attemptNumber}/${this.maxReconnectAttempts})`);
        });

        this.socket.on('reconnect_failed', () => {
            ElMessage.error('重连失败，请刷新页面重试');
        });

        this.socket.on('reconnect', (attemptNumber) => {
            console.log(`重连成功，尝试次数: ${attemptNumber}`);
            ElMessage.success('实时通讯已重新连接');
        });
    }

    // 处理认证错误
    handleAuthError() {
        ElMessage.error('登录信息已过期，请重新登录');
        // 清除登录信息
        localStorage.removeItem('imtoken');
        localStorage.removeItem('imKey');
        localStorage.removeItem('imUserInfo');
        // 断开连接
        this.disconnect();
        // 跳转到登录页
        router.push('/login');
    }

    // 添加事件监听
    on(event, callback) {
        if (!this.socket) {
            return;
        }

        this.socket.on(event, callback);
        this.listeners.set(event, callback);
    }

    // 移除事件监听
    off(event) {
        if (!this.socket) {
            return;
        }

        const callback = this.listeners.get(event);
        if (callback) {
            this.socket.off(event, callback);
            this.listeners.delete(event);
        }
    }

    // 发送消息
    emit(event, data, callback) {
        if (!this.socket || !this.isConnected) {
            return;
        }

        // 如果有回调函数
        if (typeof data === 'function') {
            callback = data;
            data = null;
        }

        if (callback) {
            this.socket.emit(event, data, callback);
        } else {
            this.socket.emit(event, data);
        }
    }

    // 断开连接
    disconnect() {
        this.imKey = null;
        if (this.socket) {
            this.socket.disconnect();
            this.socket = null;
            this.isConnected = false;
            this.listeners.clear();
        }
    }

    // 获取连接状态
    getStatus() {
        return {
            isConnected: this.isConnected,
            reconnectAttempts: this.reconnectAttempts
        };
    }
}

export default new SocketIOService(); 